package com.gzsxy.esjy.common.base.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xiaolong
 * @version 1.0
 * @description: 实体bean 转成 map对象
 * @date 2021/9/30 17:04
 */

public class ReflectUtil {

    private final static Logger log = LoggerFactory.getLogger(" ReflectUtil_log");

    /**
     * @description: Bean方法的缓存
     * @param
     * @return
     */
    private final static Map<String, Map<String, Method>> METHOD_MAP = new ConcurrentHashMap<>();

    /**
     * @param type get 或者 set
     * @param name 属性名
     * @return
     * @description: 获取get与set方法名
     */
    public static String creatMethodName(String type, String name) {
        return type + name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    /**
     * @param obj      bean对象
     * @param fileName 属性名
     * @return
     * @description: 得到get方法
     */
    public static Method getGETMethod(Object obj, String fileName) {
        if (obj == null) {
            return null;
        }
        //获取bean的class
        Class<? extends Object> clazz = obj.getClass();
        //获取类名下的所有 map属性名和方法值
        Map<String, Method> map = METHOD_MAP.get(clazz.getName());
        if (map == null) {
            map = new HashMap<>(10);
            METHOD_MAP.put(clazz.getName(), map);
        }
        //获取get与set方法名
        String methodName = creatMethodName("get", fileName);
        try {
            //获取方法
            Method method = null;

            method = map.get(methodName);

            if (method == null) {
                //获取方法
                method = clazz.getMethod(methodName);
                //关闭程序安全属性，可以获取私有属性

                map.put(methodName, method);
            }
            method.setAccessible(true);
            return method;
        } catch (NoSuchMethodException e) {
            log.error("当前属性{}方法不存在",methodName);
        }
        return null;
    }

    /**
     * @param obj      bean对象
     * @param fileName 属性名
     * @return 方法值
     * @description: 得到实体类对象（属性值存在对象中）
     */
    public static Object getObjectValue(Object obj, String fileName) {
        //获取属性名的方法
        Method method = getGETMethod(obj, fileName);
        return getObjectValue(obj, method);
    }

    /**
     * @param obj    bean对象
     * @param method 属性值方法
     * @return 方法值
     * @description: 得到实体类对象（属性值存在对象中）
     */
    public static Object getObjectValue(Object obj, Method method) {
        if (method == null || obj == null) {
            return null;
        }
        try {
            //返回的是方法值
            return method.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param bean 对象
     * @return map
     * @description: bean 转成 map
     */
    public static Map<String, Object> convertBeanToMap(Object bean) {
        Map<String, Object> map = new HashMap<>(4);
        //获取class对象
        Class<?> clazz = bean.getClass();
        try {
            //获取全部属性
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                //获取属性名
                String name = field.getName();

                //若为序列化字段
                if ("serialVersionUID".equals(name)) {
                    continue;
                }
                //得到字段值
                Object obj = getObjectValue(bean, name);
                if (obj != null) {
                    map.put(name, obj);
                }
            }
            //获取父类的class
            Class<?> superclazz = clazz.getSuperclass();
            //判断不为父类不为Object.class，说明没有父类了
            while (superclazz != Object.class) {
                //获取全部属性
                declaredFields = superclazz.getDeclaredFields();
                for (Field field : declaredFields) {
                    String name = field.getName();
                    if ("serialVersionUID".equals(name)) {
                        continue;
                    }
                    Object obj = getObjectValue(bean, name);
                    if (obj != null) {
                        map.put(name, obj);
                    }
                }
                superclazz = superclazz.getSuperclass();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
            System.out.println("反射初始化异常");
        }
        return map;
    }


//    //测试
//    public static void main(String[] args) {
//        OmsNodeInfo omsNodeInfo = new OmsNodeInfo();
//        omsNodeInfo.setId(1000);
//        Map<String, Object> map = convertBeanToMap(omsNodeInfo);
//        System.out.println(map);
//    }

}
